View Javadoc

1   /*
2    * The Apache Software License, Version 1.1
3    *
4    * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
5    * reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions
9    * are met:
10   *
11   * 1. Redistributions of source code must retain the above copyright
12   *    notice, this list of conditions and the following disclaimer.
13   *
14   * 2. Redistributions in binary form must reproduce the above copyright
15   *    notice, this list of conditions and the following disclaimer in
16   *    the documentation and/or other materials provided with the
17   *    distribution.
18   *
19   * 3. The end-user documentation included with the redistribution, if
20   *    any, must include the following acknowlegement:
21   *       "This product includes software developed by the
22   *        Apache Software Foundation (http://www.apache.org/)."
23   *    Alternately, this acknowlegement may appear in the software itself,
24   *    if and wherever such third-party acknowlegements normally appear.
25   *
26   * 4. The names "Ant" and "Apache Software
27   *    Foundation" must not be used to endorse or promote products derived
28   *    from this software without prior written permission. For written
29   *    permission, please contact apache@apache.org.
30   *
31   * 5. Products derived from this software may not be called "Apache"
32   *    nor may "Apache" appear in their names without prior written
33   *    permission of the Apache Group.
34   *
35   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46   * SUCH DAMAGE.
47   * ====================================================================
48   *
49   * This software consists of voluntary contributions made by many
50   * individuals on behalf of the Apache Software Foundation.  For more
51   * information on the Apache Software Foundation, please see
52   * <http://www.apache.org/>.
53   */
54  
55  /*
56   * This package is based on the work done by Keiron Liddle, Aftex Software
57   * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
58   * great code.
59   */
60  package com.jguild.jrpm.io.bzip2;
61  
62  import java.io.IOException;
63  import java.io.InputStream;
64  
65  /***
66   * An input stream that decompresses from the BZip2 format (without the file
67   * header chars) to be read as any other stream.
68   * 
69   * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
70   */
71  public class CBZip2InputStream extends InputStream implements BZip2Constants {
72      private static final int START_BLOCK_STATE = 1;
73  
74      private static final int RAND_PART_A_STATE = 2;
75  
76      private static final int RAND_PART_B_STATE = 3;
77  
78      private static final int RAND_PART_C_STATE = 4;
79  
80      private static final int NO_RAND_PART_A_STATE = 5;
81  
82      private static final int NO_RAND_PART_B_STATE = 6;
83  
84      private static final int NO_RAND_PART_C_STATE = 7;
85  
86      private CRC m_crc = new CRC();
87  
88      private boolean[] m_inUse = new boolean[256];
89  
90      private char[] m_seqToUnseq = new char[256];
91  
92      private char[] m_unseqToSeq = new char[256];
93  
94      private char[] m_selector = new char[MAX_SELECTORS];
95  
96      private char[] m_selectorMtf = new char[MAX_SELECTORS];
97  
98      /*
99       * freq table collected to save a pass over the data during decompression.
100      */
101     private int[] m_unzftab = new int[256];
102 
103     private int[][] m_limit = new int[N_GROUPS][MAX_ALPHA_SIZE];
104 
105     private int[][] m_base = new int[N_GROUPS][MAX_ALPHA_SIZE];
106 
107     private int[][] m_perm = new int[N_GROUPS][MAX_ALPHA_SIZE];
108 
109     private int[] m_minLens = new int[N_GROUPS];
110 
111     private boolean m_streamEnd;
112 
113     private int m_currentChar = -1;
114 
115     private int m_currentState = START_BLOCK_STATE;
116 
117     private int m_rNToGo;
118 
119     private int m_rTPos;
120 
121     private int m_tPos;
122 
123     private int i2;
124 
125     private int count;
126 
127     private int chPrev;
128 
129     private int ch2;
130 
131     private int j2;
132 
133     private char z;
134 
135     private boolean m_blockRandomised;
136 
137     /*
138      * always: in the range 0 .. 9. The current block size is 100000 * this
139      * number.
140      */
141     private int m_blockSize100k;
142 
143     private int m_bsBuff;
144 
145     private int m_bsLive;
146 
147     private InputStream m_input;
148 
149     private int m_computedBlockCRC;
150 
151     private int m_computedCombinedCRC;
152 
153     /*
154      * index of the last char in the block, so the block size == last + 1.
155      */
156     private int m_last;
157 
158     private char[] m_ll8;
159 
160     private int m_nInUse;
161 
162     /*
163      * index in zptr[] of original string after sorting.
164      */
165     private int m_origPtr;
166 
167     private int m_storedBlockCRC;
168 
169     private int m_storedCombinedCRC;
170 
171     private int[] m_tt;
172 
173     public CBZip2InputStream(final InputStream input) {
174         bsSetStream(input);
175         initialize();
176         initBlock();
177         setupBlock();
178     }
179 
180     private static void badBlockHeader() {
181         cadvise();
182     }
183 
184     private static void blockOverrun() {
185         cadvise();
186     }
187 
188     private static void cadvise() {
189         System.out.println("CRC Error");
190         // throw new CCoruptionError();
191     }
192 
193     private static void compressedStreamEOF() {
194         cadvise();
195     }
196 
197     private static void crcError() {
198         cadvise();
199     }
200 
201     public int read() {
202         if (m_streamEnd) {
203             return -1;
204         } else {
205             int retChar = m_currentChar;
206             switch (m_currentState) {
207             case START_BLOCK_STATE:
208                 break;
209             case RAND_PART_A_STATE:
210                 break;
211             case RAND_PART_B_STATE:
212                 setupRandPartB();
213                 break;
214             case RAND_PART_C_STATE:
215                 setupRandPartC();
216                 break;
217             case NO_RAND_PART_A_STATE:
218                 break;
219             case NO_RAND_PART_B_STATE:
220                 setupNoRandPartB();
221                 break;
222             case NO_RAND_PART_C_STATE:
223                 setupNoRandPartC();
224                 break;
225             default:
226                 break;
227             }
228             return retChar;
229         }
230     }
231 
232     private void setDecompressStructureSizes(int newSize100k) {
233         if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= m_blockSize100k && m_blockSize100k <= 9)) {
234             // throw new IOException("Invalid block size");
235         }
236 
237         m_blockSize100k = newSize100k;
238 
239         if (newSize100k == 0) {
240             return;
241         }
242 
243         int n = BASE_BLOCK_SIZE * newSize100k;
244         m_ll8 = new char[n];
245         m_tt = new int[n];
246     }
247 
248     private void setupBlock() {
249         int[] cftab = new int[257];
250         char ch;
251 
252         cftab[0] = 0;
253         for (int i = 1; i <= 256; i++) {
254             cftab[i] = m_unzftab[i - 1];
255         }
256         for (int i = 1; i <= 256; i++) {
257             cftab[i] += cftab[i - 1];
258         }
259 
260         for (int i = 0; i <= m_last; i++) {
261             ch = m_ll8[i];
262             m_tt[cftab[ch]] = i;
263             cftab[ch]++;
264         }
265         cftab = null;
266 
267         m_tPos = m_tt[m_origPtr];
268 
269         count = 0;
270         i2 = 0;
271         ch2 = 256;
272         /*
273          * not a char and not EOF
274          */
275         if (m_blockRandomised) {
276             m_rNToGo = 0;
277             m_rTPos = 0;
278             setupRandPartA();
279         } else {
280             setupNoRandPartA();
281         }
282     }
283 
284     private void setupNoRandPartA() {
285         if (i2 <= m_last) {
286             chPrev = ch2;
287             ch2 = m_ll8[m_tPos];
288             m_tPos = m_tt[m_tPos];
289             i2++;
290 
291             m_currentChar = ch2;
292             m_currentState = NO_RAND_PART_B_STATE;
293             m_crc.updateCRC(ch2);
294         } else {
295             endBlock();
296             initBlock();
297             setupBlock();
298         }
299     }
300 
301     private void setupNoRandPartB() {
302         if (ch2 != chPrev) {
303             m_currentState = NO_RAND_PART_A_STATE;
304             count = 1;
305             setupNoRandPartA();
306         } else {
307             count++;
308             if (count >= 4) {
309                 z = m_ll8[m_tPos];
310                 m_tPos = m_tt[m_tPos];
311                 m_currentState = NO_RAND_PART_C_STATE;
312                 j2 = 0;
313                 setupNoRandPartC();
314             } else {
315                 m_currentState = NO_RAND_PART_A_STATE;
316                 setupNoRandPartA();
317             }
318         }
319     }
320 
321     private void setupNoRandPartC() {
322         if (j2 < z) {
323             m_currentChar = ch2;
324             m_crc.updateCRC(ch2);
325             j2++;
326         } else {
327             m_currentState = NO_RAND_PART_A_STATE;
328             i2++;
329             count = 0;
330             setupNoRandPartA();
331         }
332     }
333 
334     private void setupRandPartA() {
335         if (i2 <= m_last) {
336             chPrev = ch2;
337             ch2 = m_ll8[m_tPos];
338             m_tPos = m_tt[m_tPos];
339             if (m_rNToGo == 0) {
340                 m_rNToGo = RAND_NUMS[m_rTPos];
341                 m_rTPos++;
342                 if (m_rTPos == 512) {
343                     m_rTPos = 0;
344                 }
345             }
346             m_rNToGo--;
347             ch2 ^= ((m_rNToGo == 1) ? 1 : 0);
348             i2++;
349 
350             m_currentChar = ch2;
351             m_currentState = RAND_PART_B_STATE;
352             m_crc.updateCRC(ch2);
353         } else {
354             endBlock();
355             initBlock();
356             setupBlock();
357         }
358     }
359 
360     private void setupRandPartB() {
361         if (ch2 != chPrev) {
362             m_currentState = RAND_PART_A_STATE;
363             count = 1;
364             setupRandPartA();
365         } else {
366             count++;
367             if (count >= 4) {
368                 z = m_ll8[m_tPos];
369                 m_tPos = m_tt[m_tPos];
370                 if (m_rNToGo == 0) {
371                     m_rNToGo = RAND_NUMS[m_rTPos];
372                     m_rTPos++;
373                     if (m_rTPos == 512) {
374                         m_rTPos = 0;
375                     }
376                 }
377                 m_rNToGo--;
378                 z ^= ((m_rNToGo == 1) ? 1 : 0);
379                 j2 = 0;
380                 m_currentState = RAND_PART_C_STATE;
381                 setupRandPartC();
382             } else {
383                 m_currentState = RAND_PART_A_STATE;
384                 setupRandPartA();
385             }
386         }
387     }
388 
389     private void setupRandPartC() {
390         if (j2 < z) {
391             m_currentChar = ch2;
392             m_crc.updateCRC(ch2);
393             j2++;
394         } else {
395             m_currentState = RAND_PART_A_STATE;
396             i2++;
397             count = 0;
398             setupRandPartA();
399         }
400     }
401 
402     private void getAndMoveToFrontDecode() {
403         int nextSym;
404 
405         int limitLast = BASE_BLOCK_SIZE * m_blockSize100k;
406         m_origPtr = readVariableSizedInt(24);
407 
408         recvDecodingTables();
409         int EOB = m_nInUse + 1;
410         int groupNo = -1;
411         int groupPos = 0;
412 
413         /*
414          * Setting up the unzftab entries here is not strictly necessary, but it
415          * does save having to do it later in a separate pass, and so saves a
416          * block's worth of cache misses.
417          */
418         for (int i = 0; i <= 255; i++) {
419             m_unzftab[i] = 0;
420         }
421 
422         final char[] yy = new char[256];
423         for (int i = 0; i <= 255; i++) {
424             yy[i] = (char) i;
425         }
426 
427         m_last = -1;
428         int zt;
429         int zn;
430         int zvec;
431         int zj;
432         groupNo++;
433         groupPos = G_SIZE - 1;
434 
435         zt = m_selector[groupNo];
436         zn = m_minLens[zt];
437         zvec = bsR(zn);
438         while (zvec > m_limit[zt][zn]) {
439             zn++;
440 
441             while (m_bsLive < 1) {
442                 int zzi;
443                 char thech = 0;
444                 try {
445                     thech = (char) m_input.read();
446                 } catch (IOException e) {
447                     compressedStreamEOF();
448                 }
449                 if (thech == -1) {
450                     compressedStreamEOF();
451                 }
452                 zzi = thech;
453                 m_bsBuff = (m_bsBuff << 8) | (zzi & 0xff);
454                 m_bsLive += 8;
455             }
456 
457             zj = (m_bsBuff >> (m_bsLive - 1)) & 1;
458             m_bsLive--;
459 
460             zvec = (zvec << 1) | zj;
461         }
462         nextSym = m_perm[zt][zvec - m_base[zt][zn]];
463 
464         while (true) {
465             if (nextSym == EOB) {
466                 break;
467             }
468 
469             if (nextSym == RUNA || nextSym == RUNB) {
470                 char ch;
471                 int s = -1;
472                 int N = 1;
473                 do {
474                     if (nextSym == RUNA) {
475                         s = s + (0 + 1) * N;
476                     } else// if( nextSym == RUNB )
477                     {
478                         s = s + (1 + 1) * N;
479                     }
480                     N = N * 2;
481 
482                     if (groupPos == 0) {
483                         groupNo++;
484                         groupPos = G_SIZE;
485                     }
486                     groupPos--;
487                     zt = m_selector[groupNo];
488                     zn = m_minLens[zt];
489                     zvec = bsR(zn);
490                     while (zvec > m_limit[zt][zn]) {
491                         zn++;
492 
493                         while (m_bsLive < 1) {
494                             int zzi;
495                             char thech = 0;
496                             try {
497                                 thech = (char) m_input.read();
498                             } catch (IOException e) {
499                                 compressedStreamEOF();
500                             }
501                             if (thech == -1) {
502                                 compressedStreamEOF();
503                             }
504                             zzi = thech;
505                             m_bsBuff = (m_bsBuff << 8) | (zzi & 0xff);
506                             m_bsLive += 8;
507                         }
508 
509                         zj = (m_bsBuff >> (m_bsLive - 1)) & 1;
510                         m_bsLive--;
511                         zvec = (zvec << 1) | zj;
512                     }
513 
514                     nextSym = m_perm[zt][zvec - m_base[zt][zn]];
515 
516                 } while (nextSym == RUNA || nextSym == RUNB);
517 
518                 s++;
519                 ch = m_seqToUnseq[yy[0]];
520                 m_unzftab[ch] += s;
521 
522                 while (s > 0) {
523                     m_last++;
524                     m_ll8[m_last] = ch;
525                     s--;
526                 }
527 
528                 if (m_last >= limitLast) {
529                     blockOverrun();
530                 }
531                 continue;
532             } else {
533                 char tmp;
534                 m_last++;
535                 if (m_last >= limitLast) {
536                     blockOverrun();
537                 }
538 
539                 tmp = yy[nextSym - 1];
540                 m_unzftab[m_seqToUnseq[tmp]]++;
541                 m_ll8[m_last] = m_seqToUnseq[tmp];
542 
543                 /*
544                  * This loop is hammered during decompression, hence the
545                  * unrolling. for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
546                  */
547                 int j = nextSym - 1;
548                 for (; j > 3; j -= 4) {
549                     yy[j] = yy[j - 1];
550                     yy[j - 1] = yy[j - 2];
551                     yy[j - 2] = yy[j - 3];
552                     yy[j - 3] = yy[j - 4];
553                 }
554                 for (; j > 0; j--) {
555                     yy[j] = yy[j - 1];
556                 }
557 
558                 yy[0] = tmp;
559 
560                 if (groupPos == 0) {
561                     groupNo++;
562                     groupPos = G_SIZE;
563                 }
564                 groupPos--;
565                 zt = m_selector[groupNo];
566                 zn = m_minLens[zt];
567                 zvec = bsR(zn);
568                 while (zvec > m_limit[zt][zn]) {
569                     zn++;
570 
571                     while (m_bsLive < 1) {
572                         char ch = 0;
573                         try {
574                             ch = (char) m_input.read();
575                         } catch (IOException e) {
576                             compressedStreamEOF();
577                         }
578 
579                         m_bsBuff = (m_bsBuff << 8) | (ch & 0xff);
580                         m_bsLive += 8;
581                     }
582 
583                     zj = (m_bsBuff >> (m_bsLive - 1)) & 1;
584                     m_bsLive--;
585 
586                     zvec = (zvec << 1) | zj;
587                 }
588                 nextSym = m_perm[zt][zvec - m_base[zt][zn]];
589 
590                 continue;
591             }
592         }
593     }
594 
595     private void bsFinishedWithStream() {
596         if (m_input != null) {
597             try {
598                 m_input.close();
599             } catch (IOException e) {
600             }
601         }
602         m_input = null;
603     }
604 
605     private int readVariableSizedInt(final int numBits) {
606         return bsR(numBits);
607     }
608 
609     private char readUnsignedChar() {
610         return (char) bsR(8);
611     }
612 
613     private int readInt() {
614         int u = 0;
615         u = (u << 8) | bsR(8);
616         u = (u << 8) | bsR(8);
617         u = (u << 8) | bsR(8);
618         u = (u << 8) | bsR(8);
619         return u;
620     }
621 
622     private int bsR(final int n) {
623         while (m_bsLive < n) {
624             char ch = 0;
625             try {
626                 ch = (char) m_input.read();
627             } catch (final IOException ioe) {
628                 compressedStreamEOF();
629             }
630 
631             if (ch == -1) {
632                 compressedStreamEOF();
633             }
634 
635             m_bsBuff = (m_bsBuff << 8) | (ch & 0xff);
636             m_bsLive += 8;
637         }
638 
639         final int result = (m_bsBuff >> (m_bsLive - n)) & ((1 << n) - 1);
640         m_bsLive -= n;
641         return result;
642     }
643 
644     private void bsSetStream(final InputStream input) {
645         m_input = input;
646         m_bsLive = 0;
647         m_bsBuff = 0;
648     }
649 
650     private void complete() {
651         m_storedCombinedCRC = readInt();
652         if (m_storedCombinedCRC != m_computedCombinedCRC) {
653             crcError();
654         }
655 
656         bsFinishedWithStream();
657         m_streamEnd = true;
658     }
659 
660     private void endBlock() {
661         m_computedBlockCRC = m_crc.getFinalCRC();
662         /*
663          * A bad CRC is considered a fatal error.
664          */
665         if (m_storedBlockCRC != m_computedBlockCRC) {
666             crcError();
667         }
668 
669         m_computedCombinedCRC = (m_computedCombinedCRC << 1)
670                 | (m_computedCombinedCRC >>> 31);
671         m_computedCombinedCRC ^= m_computedBlockCRC;
672     }
673 
674     private void hbCreateDecodeTables(final int[] limit, final int[] base,
675             final int[] perm, final char[] length, final int minLen,
676             final int maxLen, final int alphaSize) {
677         int pp = 0;
678         for (int i = minLen; i <= maxLen; i++) {
679             for (int j = 0; j < alphaSize; j++) {
680                 if (length[j] == i) {
681                     perm[pp] = j;
682                     pp++;
683                 }
684             }
685         }
686 
687         for (int i = 0; i < MAX_CODE_LEN; i++) {
688             base[i] = 0;
689         }
690 
691         for (int i = 0; i < alphaSize; i++) {
692             base[length[i] + 1]++;
693         }
694 
695         for (int i = 1; i < MAX_CODE_LEN; i++) {
696             base[i] += base[i - 1];
697         }
698 
699         for (int i = 0; i < MAX_CODE_LEN; i++) {
700             limit[i] = 0;
701         }
702 
703         int vec = 0;
704         for (int i = minLen; i <= maxLen; i++) {
705             vec += (base[i + 1] - base[i]);
706             limit[i] = vec - 1;
707             vec <<= 1;
708         }
709 
710         for (int i = minLen + 1; i <= maxLen; i++) {
711             base[i] = ((limit[i - 1] + 1) << 1) - base[i];
712         }
713     }
714 
715     private void initBlock() {
716         final char magic1 = readUnsignedChar();
717         final char magic2 = readUnsignedChar();
718         final char magic3 = readUnsignedChar();
719         final char magic4 = readUnsignedChar();
720         final char magic5 = readUnsignedChar();
721         final char magic6 = readUnsignedChar();
722         if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45
723                 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
724             complete();
725             return;
726         }
727 
728         if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59
729                 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
730             badBlockHeader();
731             m_streamEnd = true;
732             return;
733         }
734 
735         m_storedBlockCRC = readInt();
736 
737         if (bsR(1) == 1) {
738             m_blockRandomised = true;
739         } else {
740             m_blockRandomised = false;
741         }
742 
743         // currBlockNo++;
744         getAndMoveToFrontDecode();
745 
746         m_crc.initialiseCRC();
747         m_currentState = START_BLOCK_STATE;
748     }
749 
750     private void initialize() {
751         char magic3 = readUnsignedChar();
752         char magic4 = readUnsignedChar();
753         if (magic3 == 'B' && magic4 == 'Z') {
754             magic3 = readUnsignedChar();
755             magic4 = readUnsignedChar();
756         }
757 
758         if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {
759             bsFinishedWithStream();
760             m_streamEnd = true;
761             return;
762         }
763 
764         setDecompressStructureSizes(magic4 - '0');
765         m_computedCombinedCRC = 0;
766     }
767 
768     private void makeMaps() {
769         m_nInUse = 0;
770         for (int i = 0; i < 256; i++) {
771             if (m_inUse[i]) {
772                 m_seqToUnseq[m_nInUse] = (char) i;
773                 m_unseqToSeq[i] = (char) m_nInUse;
774                 m_nInUse++;
775             }
776         }
777     }
778 
779     private void recvDecodingTables() {
780         buildInUseTable();
781         makeMaps();
782         final int alphaSize = m_nInUse + 2;
783 
784         /*
785          * Now the selectors
786          */
787         final int groupCount = bsR(3);
788         final int selectorCount = bsR(15);
789         for (int i = 0; i < selectorCount; i++) {
790             int run = 0;
791             while (bsR(1) == 1) {
792                 run++;
793             }
794             m_selectorMtf[i] = (char) run;
795         }
796 
797         /*
798          * Undo the MTF values for the selectors.
799          */
800         final char[] pos = new char[N_GROUPS];
801         for (char v = 0; v < groupCount; v++) {
802             pos[v] = v;
803         }
804 
805         for (int i = 0; i < selectorCount; i++) {
806             int v = m_selectorMtf[i];
807             final char tmp = pos[v];
808             while (v > 0) {
809                 pos[v] = pos[v - 1];
810                 v--;
811             }
812             pos[0] = tmp;
813             m_selector[i] = tmp;
814         }
815 
816         final char[][] len = new char[N_GROUPS][MAX_ALPHA_SIZE];
817         /*
818          * Now the coding tables
819          */
820         for (int i = 0; i < groupCount; i++) {
821             int curr = bsR(5);
822             for (int j = 0; j < alphaSize; j++) {
823                 while (bsR(1) == 1) {
824                     if (bsR(1) == 0) {
825                         curr++;
826                     } else {
827                         curr--;
828                     }
829                 }
830                 len[i][j] = (char) curr;
831             }
832         }
833 
834         /*
835          * Create the Huffman decoding tables
836          */
837         for (int k = 0; k < groupCount; k++) {
838             int minLen = 32;
839             int maxLen = 0;
840             for (int i = 0; i < alphaSize; i++) {
841                 if (len[k][i] > maxLen) {
842                     maxLen = len[k][i];
843                 }
844                 if (len[k][i] < minLen) {
845                     minLen = len[k][i];
846                 }
847             }
848             hbCreateDecodeTables(m_limit[k], m_base[k], m_perm[k], len[k],
849                     minLen, maxLen, alphaSize);
850             m_minLens[k] = minLen;
851         }
852     }
853 
854     private void buildInUseTable() {
855         final boolean[] inUse16 = new boolean[16];
856 
857         /*
858          * Receive the mapping table
859          */
860         for (int i = 0; i < 16; i++) {
861             if (bsR(1) == 1) {
862                 inUse16[i] = true;
863             } else {
864                 inUse16[i] = false;
865             }
866         }
867 
868         for (int i = 0; i < 256; i++) {
869             m_inUse[i] = false;
870         }
871 
872         for (int i = 0; i < 16; i++) {
873             if (inUse16[i]) {
874                 for (int j = 0; j < 16; j++) {
875                     if (bsR(1) == 1) {
876                         m_inUse[i * 16 + j] = true;
877                     }
878                 }
879             }
880         }
881     }
882 
883     public void close() throws IOException {
884         bsFinishedWithStream();
885     }
886 }